/**
 * 
 */
package edu.alaska.uaa.cs401.fgm;

import static org.junit.Assert.*;

import java.util.ArrayList;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * @author James
 *
 */

// this will run a full, correct game.
//FanoronaBoardInterface fb = new FanoronaLinkBoard();
//fb.processMove("C 4 1 4 2",FanoronaColor.White);
//fb.processMove("W 5 3 4 4 C 4 4 4 3",FanoronaColor.Black);
//fb.processMove("C 7 0 7 1",FanoronaColor.White);
//fb.processMove("C 3 3 4 2 C 4 2 4 1 W 4 1 5 1",FanoronaColor.Black);
//fb.processMove("C 3 2 3 3 W 3 3 4 2 W 4 2 4 1 W 4 1 3 1 W 3 1 4 0",FanoronaColor.White);
//fb.processMove("C 5 2 5 1 W 5 1 4 1 W 4 1 4 2 C 4 2 3 1 W 3 1 3 2 C 3 2 2 2 C 2 2 1 1 W 1 1 1 2",FanoronaColor.Black);
//fb.processMove("C 8 2 7 3 W 7 3 6 2 W 6 2 6 1",FanoronaColor.White);
//fb.processMove("M 1 2 1 1",FanoronaColor.Black);
//fb.processMove("M 6 1 7 1",FanoronaColor.White);
//fb.processMove("M 2 3 3 3",FanoronaColor.Black);
//fb.processMove("M 7 1 7 0",FanoronaColor.White);
//fb.processMove("M 8 3 7 3",FanoronaColor.Black);
//fb.processMove("M 7 0 8 0",FanoronaColor.White);
//fb.processMove("M 7 3 7 2",FanoronaColor.Black);
//fb.processMove("M 8 0 8 1",FanoronaColor.White);
//fb.processMove("M 7 2 7 1",FanoronaColor.Black);
//fb.processMove("M 8 1 8 0",FanoronaColor.White);
//fb.processMove("W 7 1 6 2",FanoronaColor.Black);


public class FanoronaLinkBoardTest {

	/**
	 * @throws java.lang.Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}
	
	/**
	 * Test method for {@link edu.alaska.uaa.cs401.fgm.FanoronaBoard#printBoard()}.
	 */
	@Test
	public void testBoardColors() {
		FanoronaBoardInterface fb = new FanoronaLinkBoard();

		System.out.println(fb.stringBoard());
		
		class Tuple {
			public int x,y;
			public FanoronaColor q;
			Tuple(FanoronaColor q,int x,int y) {
				this.q = q; // expected value
				this.x = x; // x
				this.y = y; // y
			}
		}
		ArrayList<Tuple> al = new ArrayList<Tuple>();
		for (int x = 0; x < 8; x++) {
			al.add(new Tuple(FanoronaColor.White,x,0));
			al.add(new Tuple(FanoronaColor.White,x,1));
			if (x == 4) {
				al.add(new Tuple(null,x,2));
			} else if ( x < 4) {
				al.add(new Tuple(((x & 1) == 1)?FanoronaColor.White:FanoronaColor.Black,x,2));
			} else {
				al.add(new Tuple(((x & 1) == 0)?FanoronaColor.White:FanoronaColor.Black,x,2));
			}
			al.add(new Tuple(FanoronaColor.Black,x,3));
			al.add(new Tuple(FanoronaColor.Black,x,4));
		}
		for (Tuple q : al) {
			FanoronaColor retq = fb.getCellColor(q.x, q.y);
			if (retq != q.q) fail(String.format("Invalid piece at %d,%d expected %s got %s",q.x,q.y,q.q,retq));
		}
	}
	
	@Test
	public void testLogging() throws Exception {

		try {
			FanoronaBoardInterface fb = new FanoronaLinkBoard();
			fb.processMove("C 4 1 4 2",FanoronaColor.White);
			fb.processMove("W 5 3 4 4 C 4 4 4 3",FanoronaColor.Black);
			fb.processMove("C 7 0 7 1",FanoronaColor.White);
			fb.processMove("C 3 3 4 2 C 4 2 4 1 W 4 1 5 1",FanoronaColor.Black);
			fb.processMove("C 3 2 3 3 W 3 3 4 2 W 4 2 4 1 W 4 1 3 1 W 3 1 4 0",FanoronaColor.White);
			fb.processMove("C 5 2 5 1 W 5 1 4 1 W 4 1 4 2 C 4 2 3 1 W 3 1 3 2 C 3 2 2 2 C 2 2 1 1 W 1 1 1 2",FanoronaColor.Black);
			fb.processMove("C 8 2 7 3 W 7 3 6 2 W 6 2 6 1",FanoronaColor.White);
			fb.processMove("M 1 2 1 1",FanoronaColor.Black);
			fb.processMove("M 6 1 7 1",FanoronaColor.White);
			fb.processMove("M 2 3 3 3",FanoronaColor.Black);
			fb.processMove("M 7 1 7 0",FanoronaColor.White);
			fb.processMove("M 8 3 7 3",FanoronaColor.Black);
			fb.processMove("M 7 0 8 0",FanoronaColor.White);
			fb.processMove("M 7 3 7 2",FanoronaColor.Black);
			fb.processMove("M 8 0 8 1",FanoronaColor.White);
			fb.processMove("M 7 2 7 1",FanoronaColor.Black);
			fb.processMove("M 8 1 8 0",FanoronaColor.White);
			fb.processMove("W 7 1 6 2",FanoronaColor.Black);
			if (!fb.getLog().equals("C 4 1 4 2\nW 5 3 4 4 C 4 4 4 3\nC 7 0 7 1\nC 3 3 4 2 C 4 2 4 1 W 4 1 5 1\nC 3 2 3 3 W 3 3 4 2 W 4 2 4 1 W 4 1 3 1 W 3 1 4 0\nC 5 2 5 1 W 5 1 4 1 W 4 1 4 2 C 4 2 3 1 W 3 1 3 2 C 3 2 2 2 C 2 2 1 1 W 1 1 1 2\nC 8 2 7 3 W 7 3 6 2 W 6 2 6 1\nM 1 2 1 1\nM 6 1 7 1\nM 2 3 3 3\nM 7 1 7 0\nM 8 3 7 3\nM 7 0 8 0\nM 7 3 7 2\nM 8 0 8 1\nM 7 2 7 1\nM 8 1 8 0\nW 7 1 6 2"))
				fail("Log is invalid.");

		} catch (FanoronaMoveException e) {
			System.err.println("FanoronaMoveException: "+e.getErrorText());
			throw e;
		}
	}
	
	
	@Test
	public void testFullGame() throws Exception {
		//FanoronaBoardInterface fb = new FanoronaLinkBoard();
//		String blackcommands = "W 5 3 4 4 C 4 4 4 3\nC 3 3 4 2 C 4 2 4 1 W 4 1 5 1\nC 5 2 5 1 W 5 1 4 1 W 4 1 4 2 C 4 2 3 1 W 3 1 3 2 C 3 2 2 2 C 2 2 1 1 W 1 1 1 2\nM 1 2 1 1\nM 2 3 3 3\nM 8 3 7 3\nM 7 3 7 2\nM 7 2 7 1\nW 7 1 6 2";
//		String whitecommands = "C 4 1 4 2\nC 7 0 7 1\nC 3 2 3 3 W 3 3 4 2 W 4 2 4 1 W 4 1 3 1 W 3 1 4 0\nC 8 2 7 3 W 7 3 6 2 W 6 2 6 1\nM 6 1 7 1\nM 7 1 7 0\nM 7 0 8 0\nM 8 0 8 1\nM 8 1 8 0";
//		String[] wca = whitecommands.split("\n");
//		String[] bca = blackcommands.split("\n");
		try {
			FanoronaBoardInterface fb = new FanoronaLinkBoard();
			fb.processMove("C 4 1 4 2",FanoronaColor.White);
			fb.processMove("W 5 3 4 4 C 4 4 4 3",FanoronaColor.Black);
			fb.processMove("C 7 0 7 1",FanoronaColor.White);
			fb.processMove("C 3 3 4 2 C 4 2 4 1 W 4 1 5 1",FanoronaColor.Black);
			fb.processMove("C 3 2 3 3 W 3 3 4 2 W 4 2 4 1 W 4 1 3 1 W 3 1 4 0",FanoronaColor.White);
			fb.processMove("C 5 2 5 1 W 5 1 4 1 W 4 1 4 2 C 4 2 3 1 W 3 1 3 2 C 3 2 2 2 C 2 2 1 1 W 1 1 1 2",FanoronaColor.Black);
			fb.processMove("C 8 2 7 3 W 7 3 6 2 W 6 2 6 1",FanoronaColor.White);
			fb.processMove("M 1 2 1 1",FanoronaColor.Black);
			fb.processMove("M 6 1 7 1",FanoronaColor.White);
			fb.processMove("M 2 3 3 3",FanoronaColor.Black);
			fb.processMove("M 7 1 7 0",FanoronaColor.White);
			fb.processMove("M 8 3 7 3",FanoronaColor.Black);
			fb.processMove("M 7 0 8 0",FanoronaColor.White);
			fb.processMove("M 7 3 7 2",FanoronaColor.Black);
			fb.processMove("M 8 0 8 1",FanoronaColor.White);
			fb.processMove("M 7 2 7 1",FanoronaColor.Black);
			fb.processMove("M 8 1 8 0",FanoronaColor.White);
			fb.processMove("W 7 1 6 2",FanoronaColor.Black);
//			for (int i = 0; fb.getWinner() == null; i++) {
//				fb.processMove(wca[i],FanoronaColor.White);
//				System.out.println(fb.stringBoard());
//				if (fb.getWinner() != null) {
//					if (fb.getWinner() != FanoronaColor.White)
//						fail("Black won on white's turn.");
//					break;
//				}
//				fb.processMove(bca[i],FanoronaColor.Black);
//				System.out.println(fb.stringBoard());
//				if (fb.getWinner() != null) {
//					if (fb.getWinner() != FanoronaColor.Black)
//						fail("White won on black's turn.");
//					break;
//				}
//			}
		} catch (FanoronaMoveException e) {
			System.err.println("FanoronaMoveException: "+e.getErrorText());
		}
	}
	@Test
	public void testMoveToSame() throws Exception {
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		try {
			fb.processMove("C 4 1 4 1", FanoronaColor.White);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}
	}
	@Test
	public void testMoveToOccupied() throws Exception {
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		try {
			fb.processMove("C 4 1 3 1", FanoronaColor.White);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}
	}
	@Test
	public void testMoveWrongPiece() throws Exception {
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		try {
			fb.processMove("C 4 3 4 2", FanoronaColor.White);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}
	}
	@Test
	public void testMoveTooFar() throws Exception {
		// this is actually move to non-neighboring...
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		try {
			fb.processMove("C 0 0 4 2", FanoronaColor.White);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}
	}
	@Test
	public void testMoveOffBoard() throws Exception {
		// this is actually move to non-neighboring...
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		try {
			fb.processMove("C 8 0 9 0", FanoronaColor.White);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}
	}
	@Test
	public void testInvalidCaptureByWithdrawal() throws Exception {
		// this is actually move to non-neighboring...
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		try {
			fb.processMove("W 4 1 4 2", FanoronaColor.White);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}
	}
	@Test
	public void testMovementContinuationFromDifferentPieceNotAllowed() throws Exception {
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		fb.processMove("C 4 1 4 2",FanoronaColor.White);
		fb.processMove("W 5 3 4 4 C 4 4 4 3",FanoronaColor.Black);
		fb.processMove("C 7 0 7 1",FanoronaColor.White);
		try {
			fb.processMove("C 6 3 6 2 W 5 2 5 3",FanoronaColor.Black);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}
	}
	@Test
	public void testPaikaNotAllowed() throws Exception {
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		fb.processMove("C 4 1 4 2",FanoronaColor.White);
		fb.processMove("W 5 3 4 4 C 4 4 4 3",FanoronaColor.Black);
		fb.processMove("C 7 0 7 1",FanoronaColor.White);
		fb.processMove("C 3 3 4 2 C 4 2 4 1 W 4 1 5 1",FanoronaColor.Black);
		fb.processMove("C 3 2 3 3 W 3 3 4 2 W 4 2 4 1 W 4 1 3 1 W 3 1 4 0",FanoronaColor.White);
		fb.processMove("C 5 2 5 1 W 5 1 4 1 W 4 1 4 2 C 4 2 3 1 W 3 1 3 2 C 3 2 2 2 C 2 2 1 1 W 1 1 1 2",FanoronaColor.Black);
		fb.processMove("C 8 2 7 3 W 7 3 6 2 W 6 2 6 1",FanoronaColor.White);
		fb.processMove("M 1 2 1 1",FanoronaColor.Black);
		fb.processMove("M 6 1 7 1",FanoronaColor.White);
		fb.processMove("M 2 3 3 3",FanoronaColor.Black);
		fb.processMove("M 7 1 7 0",FanoronaColor.White);
		fb.processMove("M 8 3 7 3",FanoronaColor.Black);
		fb.processMove("M 7 0 8 0",FanoronaColor.White);
		fb.processMove("M 7 3 7 2",FanoronaColor.Black);
		fb.processMove("M 8 0 8 1",FanoronaColor.White);
		fb.processMove("M 7 2 7 1",FanoronaColor.Black);
		fb.processMove("M 8 1 8 0",FanoronaColor.White);
		//fb.processMove("W 7 1 6 2",FanoronaColor.Black);

		try {
			fb.processMove("M 7 1 6 2", FanoronaColor.Black);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}
	}

	@Test
	public void testInvalidMoveStraightLine() throws Exception {
		// this one will test if a move 
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		fb.processMove("C 3 2 4 2",FanoronaColor.White);
		fb.processMove("C 2 2 3 2",FanoronaColor.Black);

		try {
			fb.processMove("W 6 2 5 2 C 5 2 4 2", FanoronaColor.White);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}
	}
	
	//@Test
	public void testValidMoveStraightLine() throws Exception {
		// this one will test if a move 
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		fb.processMove("C 3 2 4 2",FanoronaColor.White);
		fb.processMove("C 2 2 3 2",FanoronaColor.Black);
		fb.processMove("C 4 1 4 2",FanoronaColor.White);
		fb.processMove("C 2 3 2 2",FanoronaColor.Black);
		fb.processMove("C 4 2 4 3",FanoronaColor.White);
		fb.processMove("C 2 2 2 1",FanoronaColor.Black);
		fb.processMove("C 3 1 4 1",FanoronaColor.White);
		fb.processMove("C 2 3 3 3",FanoronaColor.Black);
		fb.processMove("C 6 2 5 2",FanoronaColor.White);
		fb.processMove("C 7 3 7 2",FanoronaColor.Black);
		fb.processMove("C 1 2 2 2 C 2 2 2 3",FanoronaColor.White);
		fb.processMove("C 6 3 6 2",FanoronaColor.Black);
		fb.processMove("C 8 2 7 3",FanoronaColor.White);
		fb.processMove("C 1 3 1 2",FanoronaColor.Black);
		fb.processMove("W 5 2 4 2 W 4 2 3 1 C 3 1 3 2 C 3 2 2 2",FanoronaColor.White);
		// this move is in a straight line with itself but with one move
		// separating.
	}
	
	@Test
	public void testMoveToPriorSpace() throws Exception {
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		fb.processMove("C 3 2 4 2",FanoronaColor.White);
		try {
			fb.processMove("C 2 2 3 2 C 3 2 2 2",FanoronaColor.Black);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}		
	}
	
	@Test
	public void testInvalidCaptureByAdvancing() throws Exception {
		FanoronaBoardInterface fb = new FanoronaLinkBoard();
		fb.processMove("C 4 1 4 2",FanoronaColor.White);

		try {
			fb.processMove("C 3 3 4 3", FanoronaColor.Black);
			fail("Move was invalid but passed");
		} catch (FanoronaMoveException e) {
		}
	}
}
